package com.luoshizhen.lease.common.utils;

import com.luoshizhen.lease.common.exception.LeaseException;
import com.luoshizhen.lease.common.result.ResultCodeEnum;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;

public class JwtUtil {

    private static long tokenExpiration = 60 * 60 * 1000L;
    private static SecretKey tokenSignKey = Keys.hmacShaKeyFor("M0PKKI6pYGVWWfDZw90a0lTpGYX1d4AQ".getBytes());

    /**
     * 创建用户令牌
     *
     * 该方法生成一个JWT令牌，其中包含了用户信息，包括用户ID和用户名这个令牌用于在系统中认证用户身份
     *
     * @param userId 用户ID，用于标识用户在系统中的唯一身份
     * @param username 用户名，用户的名称标识
     * @return 返回生成的JWT令牌字符串
     */
    public static String createToken(Long userId, String username) {
        // 开始构建JWT令牌
        String token = Jwts.builder()
                // 设置令牌的主题
                .setSubject("USER_INFO")
                // 设置令牌的过期时间，当前时间加上预定义的过期时长
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
                // 在令牌中添加用户ID声明
                .claim("userId", userId)
                // 在令牌中添加用户名声明
                .claim("username", username)
                // 使用密钥对令牌进行签名，确保令牌的安全性和完整性
                .signWith(tokenSignKey)
                // 最终生成令牌字符串
                .compact();
        // 返回生成的令牌
        return token;
    }

    /**
     * 解析JWT令牌，提取并返回其中的声明信息
     *
     * @param token 待解析的JWT令牌字符串
     * @return 返回JWT令牌中的Claims（声明）对象，包含用户信息和其他自定义声明
     * @throws LeaseException 如果令牌为空、已过期或无效，将抛出此自定义异常
     */
    public static Claims parseToken(String token){
        // 检查令牌是否为空，如果为空则抛出异常，提示需要管理员登录验证
        if (token==null){
            throw new LeaseException(ResultCodeEnum.ADMIN_LOGIN_AUTH);
        }

        // 创建JwtParser对象，用于解析JWT令牌
        try{
            JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(tokenSignKey).build();
            // 使用JwtParser解析JWT令牌，并返回其中的声明信息（Claims）
            return jwtParser.parseClaimsJws(token).getBody();
        }catch (ExpiredJwtException e){
            // 捕获过期异常，提示令牌已过期
            throw new LeaseException(ResultCodeEnum.TOKEN_EXPIRED);
        }catch (JwtException e){
            // 捕获其他JWT异常，提示令牌无效
            throw new LeaseException(ResultCodeEnum.TOKEN_INVALID);
        }
    }

    /**
     * 主函数入口
     * 本函数用于演示如何创建一个令牌基于特定的用户ID和手机号
     * @param args 命令行参数，未使用
     */
    public static void main(String[] args) {
        // 输出创建的令牌
        System.out.println(createToken(8L,"15818411812"));
    }
}